package cn.bluethink.eguan.core.service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import cn.bluethink.eguan.core.entity.EgTavernEntity;
import cn.bluethink.eguan.core.mapper.EgTavernMapper;
import cn.bluethink.eguan.filter.NameFilter;
import cn.bluethink.eguan.filter.TavernFilter;
import cn.bluethink.eguan.model.core.EgBag;
import cn.bluethink.eguan.model.core.EgConfigInfo;
import cn.bluethink.eguan.model.core.EgFaction;
import cn.bluethink.eguan.model.core.EgOType;
import cn.bluethink.eguan.model.core.EgObject;
import cn.bluethink.eguan.model.core.EgTavern;
import cn.bluethink.eguan.model.core.EgUser;
import cn.bluethink.eguan.result.PageInfo;
import cn.bluethink.eguan.utils.IdMakerUtils;
import tk.mybatis.mapper.entity.Example;

@Service
public class EgTavernService extends AEgPosObjectService {

    @Autowired
    EgConfigInfo configInfo;

    @Autowired
    private EgTavernMapper tavernMapper;

    @Autowired
    private EgStaffService staffService;

    @Autowired
    private EgBagService bagService;

    @Autowired
    private EgPosObjectService posObjectService;

    @Autowired
    private EgUserService userService;

    @Autowired
    private EgFactionService factionService;

    @Autowired
    private EgMemberService memberService;

    @Autowired
    private EgTaskService taskService;

    private IdMakerUtils idUtil = new IdMakerUtils();

    @Override
    public Integer posOtype() {
        return EgOType.TAVERN;
    }

    @Override
    public EgObject pos(Long posid) throws Exception {
        return this.getById(posid);
    }

    /**
     * 创建驿馆
     * 
     * @param tavern
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public EgTavern create(EgTavern tavern, Long uid) throws Exception {
        // 1、创建驿馆包裹
        EgBag bag = bagService.create(tavern.getName() + "的包裹");
        // 2、包裹创建失败，返回空，驿馆创建失败
        if (bag == null)
            return null;
        // 3、包裹创建成功，Id生成器生成驿馆Id
        tavern.setId(idUtil.nextId());
        tavern.setBag(bag);
        // 4、获取当前登录用户所在门派，并设置门派信息
        EgFaction faction = null;
        EgObject obj = userService.currentFaction();
        // 5、如果所属门派不是江湖中，将其转换为门派对象
        if (obj != null && obj.getId() > 0) {
            faction = (EgFaction) userService.currentFaction();
        }
        tavern.setFaction(faction);
        // 6、模型转换为实体
        EgTavernEntity entity = new EgTavernEntity(tavern, true);
        entity.setUid(uid);
        // 7、创建驿馆
        int result = tavernMapper.insert(entity);
        // 8、驿馆创建失败，返回null
        if (result == 0)
            return null;
        entity.setEgid(entity.getEgid());
        return entity.createTavern();
    }

    /**
     * 删除驿馆（删除驿馆中的伙计和所有任务）
     * 
     * @param egid
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public Long del(Long egid) throws Exception {
        EgTavernEntity tavern = tavernMapper.selectByPrimaryKey(egid);
        if (tavern == null || tavern.getEgid() == 0) {
            return null;
        }
        // 1、删除驿馆中的伙计
        if (staffService.remove(egid, null) == 0L) {
            throw new RuntimeException("删除驿馆操作失败！");
        }
        // 2、删除驿馆中的所有类型的任务（建议任务加一个del_flag标记，进行逻辑删除）
        if (!taskService.removeByPos(egid, EgOType.TAVERN)) {
            throw new RuntimeException("删除驿馆操作失败！");
        }
        // 3、删除驿馆
        int delCount = tavernMapper.deleteByPrimaryKey(egid);
        if (delCount > 0) {
            // 对当前位置为该驿馆的用户，将其所在位置更新为该驿馆所属的门派/江湖
            if (!userService.changeUsersPos(egid, tavern.getFid())) {
                throw new RuntimeException("删除驿馆操作失败！");
            }
            return egid;
        }
        return null;
    }

    /**
     * 更新驿馆信息
     * 
     * @param tavern
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public EgTavern update(EgTavern tavern) throws Exception {
        EgTavernEntity entity = new EgTavernEntity(tavern, false);
        int upCount = tavernMapper.updateTavern(entity);
        if (upCount > 0) {
            entity = tavernMapper.selectByPrimaryKey(entity.getEgid());
            tavern = entity.createTavern();
            return tavern;
        }
        return null;
    }

    /**
     * 驿馆升级
     * 
     * @param tavern
     * @param staffs
     * @param uid
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public EgFaction upgrade(EgTavern tavern, List<EgUser> staffs, Long uid) throws Exception {
        String name = tavern.getName();
        String icon = "http://www.eguan.work/static/image/eguan.png";

        // 获取驿馆伙计列表
        NameFilter filter = new NameFilter();
        filter.setId(tavern.getId());
        // 获取驿馆中掌柜
        EgUser shopkeeper = staffService.getShopKeeper(tavern.getId());
        // 创建门派
        EgFaction faction = factionService.create(name, icon, shopkeeper.getId(), "ding_corp_id");
        // 添加门派成员，更新驿馆所在位置，更新当前登录人所在位置
        if (faction != null && faction.getId() > 0) {
            if (!memberService.batchAdd(faction.getId(), staffs, shopkeeper))
                throw new Exception("升级失败！");
            // 设置驿馆所属，为新门派
            tavern.setFaction(faction);
            EgTavernEntity tavernEntity = new EgTavernEntity(tavern, false);
            if (tavernMapper.updateByPrimaryKeySelective(tavernEntity) == 0)
                throw new Exception("升级失败！");
            // 设置当前登录人所在位置为该门派
            if (!userService.updatePos(uid, EgOType.FACTION, faction.getId()))
                throw new Exception("升级失败！");
            return faction;
        } else {
            throw new Exception("升级失败！");
        }
    }

    /**
     * 根据条件查询驿馆（包括驿馆所在位置信息）
     * 
     * @param filter
     * @return
     * @throws Exception
     */
    public PageInfo<EgTavern> query(TavernFilter filter) throws Exception {

        Integer pageNum = filter.getPageNum() == null ? 1 : filter.getPageNum();
        Integer pageSize = filter.getPageSize() == null ? 12 : filter.getPageSize();
        // 1、构造查询条件
        Example example = buildQueryCondition(filter);
        // 2、数据库分页查询，获取驿馆实体列表
        PageHelper.startPage(pageNum, pageSize);
        Page<EgTavernEntity> entities = (Page<EgTavernEntity>) tavernMapper.selectByExample(example);
        if (entities == null || entities.size() == 0)
            return new PageInfo<>(new ArrayList<>());
        // 3、查询成功且列表不为空，转换为驿馆模型列表
        List<EgTavern> taverns = entities.stream().map(e -> e.createTavern()).collect(Collectors.toList());
        // 4、设置驿馆所在位置信息
        setFaction(taverns);
        return new PageInfo<>(taverns, entities);
    }

    /**
     * 根据驿馆Id查询驿馆详情，包括驿馆掌柜和驿馆包裹
     * 
     * @param egid
     * @return
     * @throws Exception
     */
    public EgTavern detail(Long egid) throws Exception {
        // 1、根据驿馆Id查询驿馆信息
        EgTavernEntity entity = tavernMapper.selectByPrimaryKey(egid);
        if (entity == null)
            return null;
        // 2、驿馆实体转换为模型
        EgTavern tavern = entity.createTavern();
        // 3、将驿馆所属门派/江湖信息设置到模型中的user属性中
        EgFaction pos = (EgFaction) posObjectService.pos(tavern.getFaction().getType().getOtid(),
                tavern.getFaction().getId());
        if (pos == null) {
            pos = new EgFaction();
            pos.setId(0L);
            pos.setType(configInfo.otypes().get(EgOType.JIANGHU));
        }
        tavern.setFaction(pos);
        // 3、将驿馆掌柜信息设置到模型中的user属性中
        EgUser shopkeeper = staffService.getShopKeeper(egid);
        if (shopkeeper != null) {
            shopkeeper = userService.getUserBasic(shopkeeper.getId());
        } else {
            shopkeeper = new EgUser();
        }
        tavern.setUser(shopkeeper);
        // 4、设置当前驿馆的包裹信息
        EgBag bag = new EgBag(tavern.getId(), null);
        tavern.setBag(bag);
        // 5、设置当前对象类型名
        EgOType type = configInfo.otypes().get(EgOType.TAVERN);
        tavern.setType(type);
        return tavern;
    }

    /**
     * 根据驿馆Id获取当前驿馆基本信息
     * 
     * @param egid
     * @return
     * @throws Exception
     */
    public EgTavern getById(Long egid) throws Exception {
        // 1、根据驿馆Id查询驿馆信息
        EgTavernEntity entity = tavernMapper.selectByPrimaryKey(egid);
        if (entity == null) {
            return null;
        }
        // 2、驿馆实体转换为模型
        EgTavern tavern = new EgTavern(egid, entity.getName(), null);
        // 3、将驿馆所属门派/江湖信息设置到模型中的tavern属性中
        Long fid = entity.getFid();
        EgFaction pos = null;
        if (fid == null || fid == 0L) {
            pos = new EgFaction(0L, configInfo.otypes().get(EgOType.JIANGHU).getName(), null);
        } else {
            pos = (EgFaction) posObjectService.pos(EgOType.FACTION, entity.getFid());
        }
        tavern.setFaction(pos);
        return tavern;
    }

    /**
     * 根据门派的ID获取旗下驿馆季度年的开始月份
     * 
     * @param egid
     * @return
     * @throws Exception
     */
    public Integer getBmonthByFid(Long egid) throws Exception {
        EgTavernEntity entity = tavernMapper.selectByPrimaryKey(egid);
        if (entity == null) {
            return 1;
        } else {
            Long fid = entity.getFid();
            return fid == null ? 1 : factionService.getBmonthByFid(fid);
        }
    }

    /**
     * 根据门派Id获取驿馆Id列表
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    public List<Long> egidsByFid(Long fid) throws Exception {
        Example example = new Example(EgTavernEntity.class);
        example.and().andCondition("IFNULL(fid,0) = " + fid);
        List<EgTavernEntity> entities = tavernMapper.selectByExample(example);
        List<Long> result = new ArrayList<>();
        if (entities != null && entities.size() > 0) {
            result = entities.stream().map(e -> e.getEgid()).collect(Collectors.toList());
        }
        return result;
    }

    /**
     * 根据门派Id获取驿馆对应包裹ID列表
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    public List<Long> bagsByFid(Long fid) throws Exception {
        Example example = new Example(EgTavernEntity.class);
        example.and().andEqualTo("fid", fid);
        List<Long> result = new ArrayList<>();
        List<EgTavernEntity> entities = tavernMapper.selectByExample(example);
        if (entities != null && entities.size() > 0) {
            result = entities.stream().map(e -> e.getBagid()).collect(Collectors.toList());
        }
        return result;
    }

    /**
     * 判断当前驿馆是否在给定的门派中
     * 
     * @param fid
     * @param egid
     * @return
     * @throws Exception
     */
    public Boolean existInFaction(Long fid, Long egid) throws Exception {
        Example example = new Example(EgTavernEntity.class);
        example.and().andEqualTo("fid", fid).andEqualTo("egid", egid);
        int selCount = tavernMapper.selectCountByExample(example);
        return selCount > 0 ? true : false;
    }

    /**
     * 根据门派ID删除旗下所有的驿馆
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public Boolean delTavernByFid(Long fid) throws Exception {
        Example example = new Example(EgTavernEntity.class);
        example.and().andEqualTo("fid", fid);
        int delCount = tavernMapper.deleteByExample(example);
        return delCount > 0 ? true : false;
    }

    /**
     * 驿馆伙计邀请
     * 
     * @param egid
     * @param uid
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public Boolean invite(Long egid, Long uid) throws Exception {
        // 添加用户为驿馆伙计
        if (staffService.create(egid, uid) == null) {
            throw new RuntimeException("邀请失败，请重试！");
        }
        // 更新用户位置为当前驿馆
        if (!userService.updatePos(uid, EgOType.TAVERN, egid)) {
            throw new RuntimeException("邀请失败，请重试！");
        }
        return true;
    }

    /**
     * 构造查询条件
     * 
     * @param filter
     * @return
     * @throws Exception
     */
    private Example buildQueryCondition(TavernFilter filter) throws Exception {
        Example example = new Example(EgTavernEntity.class);

        // Long objid = null; // 驿馆所在地Id（门派/江湖）
        Long cuid = null; // 驿馆创建者Id
        Long fid = filter.getFid() == null ? 0 : filter.getFid();// 门派/江湖Id
        // boolean beWorkbench = filter.getBeWorkbench() == null ? false :
        // filter.getBeWorkbench(); // 是否查询工作台中的驿馆列表
        Long uid = filter.getStaffid(); // 用户Id，查询当前用户所属驿馆列表

        // 1、如果buid为空，默认为false
        boolean buid = filter.getBuid() == null ? true : filter.getBuid();
        // 2、buid == false ，根据驿馆所在对象Id查询；否则，根据驿馆创建者Id和参数fid查询fid对应门派/江湖中该用户创建的驿馆
        if (buid) {
            cuid = (filter.getId() == null || filter.getId() == 0) ? null : filter.getId();
        }
        // 3、构造查询条件fid
        if (fid != null && fid > 0) {
            /*
             * if (beWorkbench) { example.and().andCondition("IFNULL(fid,0) = " + fid); }
             * else if (fid > 0) { example.and().andEqualTo("fid", fid); }
             */
            example.and().andEqualTo("fid", fid);
        }
        // 4、构造查询条件cuid
        if (cuid != null && cuid > 0) {
            example.and().andEqualTo("uid", cuid);
        }
        // 5、构造查询条件uid
        if (uid != null && uid > 0) {
            List<Long> tids = staffService.taverIdsByUser(uid);
            // 如果我所属的驿馆不为空，查询当前门派中我所属驿馆列表
            if (tids != null && tids.size() > 0) {
                example.and().andIn("egid", tids);
            }
            // 否则，我所属驿馆为空
            else {
                example.and().andCondition("fid < 0");
            }
        }

        example.orderBy("ctime").desc();
        return example;
    }

    /**
     * 循环遍历驿馆列表，获取所在门派信息，并设置（如果是江湖，不设置门派信息）
     * 
     * @param taverns
     * @throws Exception
     */
    private void setFaction(List<EgTavern> taverns) throws Exception {
        for (EgTavern tavern : taverns) {
            EgFaction faction = null;
            if (tavern.getFaction() == null || tavern.getFaction().getId() == 0) {
                faction = new EgFaction();
            } else {
                faction = (EgFaction) posObjectService.pos(tavern.getFaction().getType().getOtid(),
                        tavern.getFaction().getId());
                if (faction == null)
                    faction = new EgFaction();
            }
            tavern.setFaction(faction);
        }
    }
}